package adventure.commands;

import adventure.*;
import adventure.misc.Currency;
import adventure.placeable.Item;
import adventure.placeable.Mobile;
import colour.ColourUtil;
import java.util.ArrayList;
import player.*;

/**
 *
 * @author Michael Hanns
 *
 */
public class Sell extends AbstractCommand {

    Currency currency;

    public Sell(Adventure a) {
        super(a, new String[]{"SELL"});
        this.currency = a.getCurrency();
    }

    @Override
    public String validateAndExecute(Player p, String[] args) {
        if (((AdventureEdit) adv).getRoomManager().isLightPresent(p.x(), p.y(), p.z())) {
            if (args.length == 1) {
                return listItems(p);
            } else if (((AdventureEdit) adv).getRoomManager().isLightPresent(p.x(), p.y(), p.z())) {
                int fromPosition = 0;
                for (int x = 0; x < args.length; x++) {
                    if (args[x].equalsIgnoreCase("to")) {
                        fromPosition = x;
                    }
                }

                if (args.length > 1 && fromPosition > 1) {
                    String item = args[1];
                    for (int x = 2; x < fromPosition; x++) {
                        item = item.concat(" ".concat(args[x]));
                    }

                    if (fromPosition < args.length - 1) {
                        String target = args[fromPosition + 1];

                        for (int x = fromPosition + 2; x < args.length; x++) {
                            target = target.concat(" ".concat(args[x]));
                        }
                        return sell(p, item, target);
                    } else {
                        return "Sell " + item + " to whom?\nSyntax: sell <item> [to <mobile>]";
                    }
                } else {
                    String item = args[1];
                    for (int x = 2; x < args.length; x++) {
                        item = item.concat(" ".concat(args[x]));
                    }

                    return sell(p, item);
                }
            }
            return "Sell what from whom?\nSyntax: sell <item> [to <mobile>]";
        } else {
            return "You cannot see anything in the darkness!";
        }
    }

    private String listItems(Player player) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);

        String output = "";

        Item item;
        int n;
        for (int c = 0; c < vendors.length; c++) {
            n = 0;

            output += ColourUtil.colourise(vendors[c].getAliveName(), ColourUtil.mobile)
                    + " will offer you:\n";
            output += ColourUtil.colourise("---\n", ColourUtil.yellow);

            if (player.getInventoryItem(0).getID() != 0) {

                int maxLength = 0;
                int maxTypeLength = 0;
                int usesLength;
                int maxUsesLength = 0;

                while ((item = player.getInventoryItem(n++)).getID() != 0) {
                    if (item.getName().length() > maxLength) {
                        maxLength = item.getName().length();
                    }

                    if (item.getItemType().length() > maxTypeLength) {
                        maxTypeLength = item.getItemType().length();
                    }

                    if (item.isConsumable()) {
                        usesLength = String.valueOf(item.getUsesLeft()).length()
                                + String.valueOf(item.getTotalUses()).length() + 10;
                        if (usesLength > maxUsesLength) {
                            maxUsesLength = usesLength;
                        }
                    }
                }
                n = 0;

                while ((item = player.getInventoryItem(n++)).getID() != 0) {
                    String namePlusWhiteSpace = item.getName();
                    while (namePlusWhiteSpace.length() < maxLength) {
                        namePlusWhiteSpace += " ";
                    }
                    namePlusWhiteSpace = ColourUtil.colourise(namePlusWhiteSpace, ColourUtil.item);

                    String itemTypePlusWhiteSpace = item.getItemType();
                    while (itemTypePlusWhiteSpace.length() < maxTypeLength) {
                        itemTypePlusWhiteSpace += " ";
                    }
                    
                    String itemUsesPlusWhiteSpace;
                    if(item.isConsumable()) {
                        itemUsesPlusWhiteSpace = " (uses: "
                            + item.getUsesLeft() + "/" + item.getTotalUses() + ")";
                    } else {
                        itemUsesPlusWhiteSpace = "";
                    }
                    while (itemUsesPlusWhiteSpace.length() < maxUsesLength) {
                        itemUsesPlusWhiteSpace += " ";
                    }
                    
                    int price = getSellPrice(item, vendors[c].getVendorModifier());
                    String currencyCost;
                    if (price > 1) {
                        currencyCost = ColourUtil.colourise(price + " " + currency.getPlural(), ColourUtil.currency);
                    } else {
                        currencyCost = ColourUtil.colourise(price + " " + currency.getSingular(), ColourUtil.currency);
                    }

                    output += namePlusWhiteSpace
                            + " : " + itemTypePlusWhiteSpace
                            + itemUsesPlusWhiteSpace
                            + " - " + currencyCost + "\n";
                }
            } else {
                output += "You have nothing to sell.\n";
            }

            if (c != vendors.length - 1) {
                output += "\n";
            }
        }

        if (output.length() == 0) {
            output = "There are no vendors here to sell to!";
        }


        return output;
    }

    private String sell(Player player, String targetItem, String targetVendor) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);
        Item item;

        String vendorName = "";
        for (int c = 0; c < vendors.length; c++) {
            for (int d = 0; (item = player.getInventoryItem(d)).getID() != 0; d++) {
                if (item.getName().toUpperCase().startsWith(targetItem.toUpperCase())) {
                    if (vendors[c].getName().toUpperCase().startsWith(targetVendor.toUpperCase())) {
                        return itemTransaction(player, item, vendors[c]);
                    }
                }
                vendorName = vendors[c].getAliveName();
            }
        }

        if (vendorName.length() > 0) {
            return "You don't have any " + targetItem + " to sell to "
                    + ColourUtil.colourise(vendorName, ColourUtil.mobile) + "!";
        }

        return "You don't see any " + targetVendor + " to sell " + targetItem + " to!";
    }

    private String sell(Player player, String targetItem) {
        int x = player.x();
        int y = player.y();
        int z = player.z();

        Mobile[] vendors = rooms.getRoomVendors(x, y, z);

        if (vendors.length > 0) {

            // We're looking to find the highest paying vendor. Vendors that can't afford are marked -1
            int[] vendorPrices = new int[vendors.length];

            Item item = player.getInventoryItem(0);
            int sellPrice;

            boolean foundItem = false;
            for (int d = 0; !foundItem && (item = player.getInventoryItem(d)).getID() != 0; d++) {
                if (item.getName().toUpperCase().startsWith(targetItem.toUpperCase())) {
                    for (int c = 0; c < vendors.length; c++) {
                        sellPrice = getSellPrice(item, vendors[c].getVendorModifier());
                        if (vendors[c].getCurrencyContents() >= sellPrice) {
                            vendorPrices[c] = sellPrice;
                        } else {
                            vendorPrices[c] = -1;
                        }
                    }
                    foundItem = true;
                }
            }

            if (!foundItem) {
                return "You don't have any " + targetItem + " to sell!";
            } else {

                // Now we've got the prices, we find the highest
                int highestPrice = -1;

                // and take note of which position in the array they are
                int highestPayingPosition = -1;
                System.out.println("Prices:");
                for (int c = 0; c < vendorPrices.length; c++) {
                    System.out.println("Vendor " + c + " Price: " + vendorPrices[c]);
                    if (vendorPrices[c] > highestPrice) {
                        highestPrice = vendorPrices[c];
                        highestPayingPosition = c;
                        System.out.println("Highest paying position: " + c);
                    }
                }

                // Sell to the highest bidder!
                if (highestPayingPosition > -1) {
                    return itemTransaction(player, item, vendors[highestPayingPosition]);
                } // Otherwise, tell the player they can't afford what they're selling
                else {
                    String vendorNames = "";
                    if (vendors.length > 1) {
                        for (int c = 0; c < vendors.length - 1; c++) {
                            vendorNames += ColourUtil.colourise(
                                    vendors[0].getName().toUpperCase().substring(0, 1)
                                    + vendors[0].getName().substring(1), ColourUtil.mobile);
                            if (c != vendors.length - 2) {
                                vendorNames += ", ";
                            }
                        }
                        vendorNames += " or " + ColourUtil.colourise(
                                vendors[vendors.length - 1].getName().toUpperCase().substring(0, 1)
                                + vendors[vendors.length - 1].getName().substring(1), ColourUtil.mobile);

                        return vendorNames
                                + " do not have enough " + currency.getPlural() + " to pay for "
                                + ColourUtil.colourise(item.getName(), ColourUtil.item) + "!";
                    } else {
                        vendorNames = vendors[0].getName().toUpperCase().substring(0, 1)
                                + vendors[0].getName().substring(1);
                        return ColourUtil.colourise(
                                vendorNames, ColourUtil.mobile)
                                + " does not have enough " + currency.getPlural() + " to pay for "
                                + ColourUtil.colourise(item.getName(), ColourUtil.item) + "!";

                    }
                }

            }
        } else {
            return "There is no-one to sell " + targetItem + " to!";
        }
    }

    private String itemTransaction(Player player, Item item, Mobile vendor) {
        if (item.isBound()) {
            return ColourUtil.colourise(item.getName(), ColourUtil.item) + " is bound to you!";
        } else if (item.isTemporary()) {
            return "You cannot sell temporary items!";
        } else {
            int itemPrice = getSellPrice(item, vendor.getVendorModifier());

            if (vendor.getCurrencyContents() >= itemPrice) {
                player.giveCurrencyAmount(itemPrice);
                vendor.takeCurrencyAmount(itemPrice);
                vendor.addInventoryItem(item);
                player.removeInventoryItem(item.getName());

                String priceOut;
                if (itemPrice == 1) {
                    priceOut = "a " + currency.getSingular();
                } else {
                    priceOut = itemPrice + " " + currency.getPlural();
                }

                out.broadcastLocalToPlayer(player,
                        ColourUtil.colourise(player.getAliveName(), ColourUtil.player)
                        + " sells " + ColourUtil.colourise(item.getName(), ColourUtil.item)
                        + " to " + ColourUtil.colourise(vendor.getName(), ColourUtil.mobile)
                        + " for " + ColourUtil.colourise(priceOut, ColourUtil.currency)
                        + ".");

                return "You sell " + ColourUtil.colourise(item.getName(), ColourUtil.item)
                        + " to " + ColourUtil.colourise(vendor.getName(), ColourUtil.mobile)
                        + " for " + ColourUtil.colourise(priceOut, ColourUtil.currency)
                        + ".";
            }


            return ColourUtil.colourise(vendor.getName(), ColourUtil.mobile)
                    + " does not have enough " + currency.getPlural() + " to pay for "
                    + ColourUtil.colourise(item.getName(), ColourUtil.item) + "!";
        }
    }

    private int getSellPrice(Item item, double vendorMod) {
        double baseValue = item.getCurrencyValue();
        
        if(item.isConsumable()) {
            baseValue = baseValue * ((double)item.getUsesLeft() / (double)item.getTotalUses());
        }
        
        return (int) (baseValue - (baseValue * vendorMod / 100));
    }
}
